AWS LambdaをHaskellで実装!aws-lambda-haskell-runtimeを試してみた。
こちらはAWS Lambda Custom Runtimes芸人 Advent Calendar 2018の22日目の記事です。
こんにちは、かたいなかです。
AWS LambdaのCustom RuntimeでHaskellを動かすためのCustom RuntimeのLayerの実装、およびそのRuntime上でアプリケーションコードを実装するためのTemplate等がtheam/aws-lambda-haskell-runtime
というGitHub上のリポジトリにあり、ビルドされたものがRuntime Layerとして利用できるようになっているのを発見したため、試してみた内容を記事にまとめました。
ローカルでの準備
まず、以下のようなコードを実行し、ローカルに今回使用するコードの展開を行います。
$ stack new <repository名> https://github.com/theam/aws-lambda-haskell-runtime/raw/master/stack-template.hsfiles \ --resolver=lts-12.13 --omit-packages #テンプレートを展開 $ cd <repository名> #作成されたディレクトリに入る
次に、ビルド環境として使用するstack-build
のDockerイメージをPullしておきます。
$ stack docker pull #ビルド環境として使用するDockerイメージをPull
最後に、stack.yml
に上記のような内容を追加します。
packages: - . extra-deps: - aws-lambda-haskell-runtime-1.0.4
ここまでの準備で、Lambdaにアップロードできるbuild/function.zip
がmake
コマンドにより作成できるようになっています。
テンプレートから作成されたリポジトリの内容
ここまでの処理で以下のようなファイルが作成されます
- .stack-work - (省略) - app - Main.hs - src - Lib.hs - .gitignore - LISCENCE - Makefile - <repository名>.cabal - package.yaml - README.md - Setup.hs - stack.yaml
src/Lib.hs
ではハンドラを定義しています。
module Lib where import GHC.Generics import Aws.Lambda.Runtime import Data.Aeson data Person = Person { personName :: String , personAge :: Int } deriving (Generic) instance FromJSON Person instance ToJSON Person handler :: Person -> Context -> IO (Either String Person) handler person context = if personAge person > 0 then return (Right person) else return (Left "A person's age must be positive")
他の言語のHandler同様にEventとContextを受け取る形で実装されています。
処理の内容としては以下のようなJsonを受け取り、personAge
が正であることを確認したうえで受け取ったJsonと同じものを返すというものです。
{ "personName": "katainaka" "personAge": 3 }
app/Main.hs
は以下のようなコードで、Template Haskellを使用して動的にhandlerにディスパッチする処理を生成しているようです。
module Main where import Aws.Lambda.Configuration import Aws.Lambda.Runtime import qualified Lib configureLambda
動作確認
実際にデプロイしていきます。
リポジトリのルートディレクトリでmake
コマンドを実行します。
$ make
すると、build
ディレクトリの下にfunction.zip
というファイルが作成されます。
以下のようなコマンドですでに公開されているRuntimeのLayerと合わせてFunctionを作成します。
$ aws lambda create-function --function-name "haskell-lambda" \ --zip-file "fileb://build/function.zip" \ --handler "src/Lib.handler" \ --runtime provided \ --layers arn:aws:lambda:<YOUR REGION>:785355572843:layer:haskell-runtime:<VERSION> ##公開されているRuntimeのLayerのARNです --role arn:aws:iam::XXXXXXXXXXXX:role/your-lambda-role
Functionを作成したら、コンソール上から試していきます。
以下のようなテストイベントを作成して実行すると
以下のように実行に成功し、正しく結果が返されました!
感想
re:Inventでの発表からそれほど日がたっていないにもかかわらず、すでにHaskellのRuntimeの実装例がRuntime LayerのARNを指定すれば誰でも利用可能な状態になっており、関連したパッケージがCabalに登録されているのには驚きました。
今回はテンプレートから生成されたコードを実行してみただけでしたが、Haskellがお好きな方は是非本格的に試してみてはいかがでしょうか。